import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../resources.dart';
import 'base_model.dart';

/// created by hcl
/// on 2023/3/6
/// page base_page
/// desc
abstract class BaseState<T extends BaseModel, P extends StatefulWidget>
    extends State<P> with AutomaticKeepAliveClientMixin {
  @override
  @protected
  bool get wantKeepAlive => false;

  final FocusNode _blankNode = FocusNode();

  late T model;

  T initModel();

  @protected
  Widget appBarWidget() {
    return commonTitleBar(title, onTap: () {
      hideKeyboard();
      if (canPop) {
        baseBack.call();
      }
    }, rightAction: action);
  }

  @protected
  Widget bodyWidget(BuildContext context);

  @protected
  List<Widget> otherWidget(BuildContext context) => [];

  @protected
  Widget? loadingWidget(BuildContext context) => null;

  @protected
  Widget? emptyWidget(BuildContext context) => null;

  @protected
  Widget? errorWidget(BuildContext context) => null;

  Widget? navigationBarWidget() => null;

  @protected
  Widget? floatingActionButtonWidget() => null;

  Widget _buildLoading(context) {
    return loadingWidget(context) ?? loadingComponents();
  }

  Widget _buildEmpty(context) {
    return emptyWidget(context) ?? stateComponents(emptyStr);
  }

  Widget _buildError(context) {
    return errorWidget(context) ?? stateComponents(errorStr);
  }

  ///是否显示appBar
  @protected
  bool get showAppBar => true;

  ///是否 resizeToAvoidBottomInset 软键盘相关
  @protected
  bool get bottomInset => false;

  @protected
  String get title => '';

  @protected
  String get emptyStr => word.empty;

  @protected
  String get errorStr => word.error;

  @protected
  Color get backColor => ColorUtils.color_FFFFFF;

  @protected
  bool get isLight => true;

  @protected
  Widget get action => const SizedBox();

  @protected
  bool get canPop => true;

  @protected
  VoidCallback get baseBack => () {
        Nav.pop(result: null);
      };

  @override
  @protected
  void initState() {
    model = initModel();
    model.mContext = context;
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((callback) {
      model.initData();
    });
  }

  @override
  @protected
  void dispose() {
    // model.dispose();
    super.dispose();
  }

  void hideKeyboard() {
    FocusScope.of(context).requestFocus(_blankNode);
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return PopScope(
      canPop: canPop,
      child: ChangeNotifierProvider<T>(
        create: (context) => model,
        child: Scaffold(
          resizeToAvoidBottomInset: bottomInset,
          backgroundColor: backColor,
          body: Center(
            child: SizedBox(
              width: designWidth.ss,
              child: GestureDetector(
                onTap: () {
                  hideKeyboard();
                },
                child: Selector<T, StateEnum>(
                  selector: (context, model) {
                    return model.state;
                  },
                  builder: (context, state, parent) {
                    return Column(
                      children: [
                        showAppBar ? appBarWidget() : const SizedBox(),
                        Expanded(
                          child: _buildBody(context),
                        ),
                      ],
                    );
                  },
                ),
              ),
            ),
          ),
          bottomNavigationBar: navigationBarWidget() ?? null,
          floatingActionButton: floatingActionButtonWidget() ?? null,
        ),
      ),
    );
  }

  Widget _buildBody(context) {
    if (model.state == StateEnum.success) {
      return bodyWidget(context);
    } else if (model.state == StateEnum.error) {
      return _buildError(context);
    } else if (model.state == StateEnum.empty) {
      return _buildEmpty(context);
    } else {
      return _buildLoading(context);
    }
  }

  Widget loadingComponents() {
    return SizedBox(
      width: double.infinity,
      height: 300,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          const CircularProgressIndicator(
            backgroundColor: ColorUtils.color_999999,
            color: ColorUtils.color_3C6EF0,
          ),
          const SizedBox(height: 20),
          Text(word.loading, style: normal616)
        ],
      ),
    );
  }

  Widget stateComponents(String info, {Widget icon = const SizedBox()}) {
    return SizedBox(
      width: double.infinity,
      height: 300,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          icon,
          Text(info, style: normal616),
        ],
      ),
    );
  }
}
